Projekt z zakresu eksploracji danych
Cel projektu
Projekt ma na celu zbadanie wpływu słów kluczowych używanych w opiniach na ostateczną ocenę (liczbę gwiazdek) i rekomendację danego produktu pozostawioną przez klientów. Dodatkowo przeprowadzona została analiza poszczególnych zmiennych oraz sprawdzenie czy zbiór nie posiada ukrytych związków między predyktorami.
Zbiór danych
W zbiorze danych znajdują się informacje dotyczące zarówno klientów, ich zakupów jak i oceny danych produktów.
Wczytanie danych
Poniższa tabela prezentuje część zbioru danych.
Opis zmiennych
| Oryginalna nazwa zmiennej | Wyjaśnienie |
|---|---|
| Product ID | Numer ID produktu |
| Category | Kategoria |
| Subcategory1 | Podkategoria pierwsza |
| Subcategory2 | Podkategoria druga |
| Location | Lokalizacja klienta/klientki |
| Channel | Sposób zamieszczenia opinii (poprzez urządzenie mobilne lub stronę internetową) |
| Customer Age | Wiek klienta/klientki w latach |
| Review Title | Tytuł opinii |
| Review Text | Treść opinii |
| Rating | Ilość gwiazdek nadanych przez klienta/klientkę |
| Recommend Flag | Czy klient/klientka rekomenduje dany produkt |
Ponieważ nie skupiamy się na konkretnych produktach, tylko głównie na wpływie opinii na ilość gwiazdek i rekomendację, to kolumnę Product ID możemy usunąć. Zostaje dodany nowy unikalny numer ID do każdej obserwacji.
Usunięte zostają również kolumny Subcategory1 oraz Subcategory2 - ogólny podział na kategorie produktów wydaje się być wystarczający.
Sprawdzanie poprawności zbioru danych
Braki danych
Powyższa tabela przedstawia wiersze, w których pojawiają się braki danych. Występują one w kolumnach takich jak: Category, Review Title, Review Text.
| Braki | |
|---|---|
Category |
14 |
Location |
0 |
Channel |
0 |
Customer Age |
0 |
Review Title |
3810 |
Review Text |
845 |
Rating |
0 |
Recommend Flag |
0 |
| Id | Category | Location | Channel | Customer Age | Review Title | Review Text | Rating | Recommend Flag |
|---|---|---|---|---|---|---|---|---|
| 93 | General Petite | Gurgaon | Mobile | 23 | NA | NA | 5 | 1 |
| 94 | General | Gurgaon | Mobile | 31 | NA | NA | 5 | 1 |
| 99 | General | Mumbai | Mobile | 50 | NA | NA | 5 | 1 |
| 136 | General Petite | Gurgaon | Web | 35 | NA | NA | 4 | 1 |
| 143 | General | Gurgaon | Web | 35 | NA | NA | 5 | 1 |
| 166 | General Petite | Bangalore | Web | 35 | NA | NA | 3 | 0 |
| Id | Category | Location | Channel | Customer Age | Review Title | Review Text | Rating | Recommend Flag |
|---|---|---|---|---|---|---|---|---|
| 10221 | General | Chennai | Mobile | 30 | Such a beautiful dress! | NA | 5 | 1 |
Zazwyczaj gdy nie ma podanego tekstu opinii, to nie ma też jej tytułu. W tym zbiorze występuje jedna obserwacja, w której jest sam tytuł bez opinii. Jeżeli chodzi o zmienne Review Title oraz Review Text, to jest aż 2965 opinii bez nadanego tytułu. Można przypuszczać, że system, który obsługuje klientów tego sklepu pozwala na umieszczenie opinii bez nadawania tytułu.
Ostatecznie, obserwacje, które zawierają braki danych zostają usunięte, ponieważ nie będą przydatne.
Duplikaty
W ramce danych nie występują duplikaty.
Zamiana typów zmiennych
| Category | Location | Channel | Rating | Recommend.Flag |
|---|---|---|---|---|
| General, General Petite, Initmates | Bangalore, Chennai, Gurgaon, Mumbai | Mobile, Web | 1, 2, 3, 4, 5 | 0, 1 |
Zmienne typu character zostają zamienione na factor (oprócz zmiennych Review Title oraz Review Text). Table 5 przedstawia kategorie tych zmiennych.
Obserwacje odstające
Tak jak widać na Figure 1, obserwacje odstające zmiennej Customer Age to te, które mają bardzo dużą wartość tej zmiennej. Zostają one usunięte ze zbioru danych.
Analiza tekstu - opinii
Jednym z celów projektu jest analiza tekstu, czyli różnych opinii i tego, jak słowa, które znajdują się w tekście, wpływają na ostateczną ocenę danego produktu. Zanim przejdziemy do modelowania, warto spojrzeć jakie wyrażenia pojawiają się w opiniach najczęściej. Można również sprawdzić najpopularniejsze słowa w podziale na części mowy takie jak: rzeczowniki, czasowniki, przymiotniki. W tym przypadku wykorzystywany jest model języka angielskiego, bo w takim napisane są opinie.
Najczęściej pojawiają się rzeczowniki, a zaraz po nich znaki interpunkcyjne.
Analiza rzeczowników
Można założyć, że najczęściej klinetki kupują sukienki, bo wspominają o nich w opiniach wielokrotnie. Podczas oceniania produktów często odnoszą się do rozmiaru danego ubrania.
Analiza czasowników
Powyższy wykres przedstawia czasowniki, które są najchętniej używane podczas oceniania produktów.
Analiza przymiotników
Analiza słów kluczowych
Powyższy wykres identyfikuje słowa kluczowe za pomocą algorytmu RAKE (Rapid Automatic Keyword Extraction). Jego algorytm dzieli tekst na frazy kandydatów, używając stop - words (np. the, is, an) jako delimiterów (“oddzielaczy”), a następnie ocenia te frazy na podstawie częstotliwości współwystępowania słów. Na końcu wybiera określoną liczbę najistotniejszych słów kluczowych lub fraz, które najlepiej reprezentują zawartość tekstu.
Dla porównania z algorytmem RAKE, powyższy wykres bada częstotliwość fraz, ale prostą metodą wyrażeń z rzeczownikami i czasownikami. Widać, że pokazuje całkowicie inne wyniki niż poprzednia wizualizacja.
Word cloud
Word cloud to jedno z narzędzi wizualizacji, które pozwala na przejrzyste przedstawienie najczęściej pojawiających się sformułowań użytych w tekście.
Analiza zbioru danych
Podstawowe statystyki opisowe
| Age | |
|---|---|
| Min. :18.00 | |
| 1st Qu.:34.00 | |
| Median :41.00 | |
| Mean :43.26 | |
| 3rd Qu.:52.00 | |
| Max. :99.00 |
| skośność | kurtoza |
|---|---|
| 0.5155924 | 2.860005 |
Na podstawie Table 7 oraz Figure 2 można powiedzieć, że rozkład zmiennej Customer Age jest prawostronnie asymetryczny w porównaniu do rozkładu normalnego - dominują jednostki mniejsze od średniej. Kurtoza jest bliska wartości 3, więc “szpiczastość” rozkładu jest podobna do normalnego.
Zmienna Customer Age w podziale na grupy
Jak widać na powyższych wykresach, nie ma dużych różnic w wieku klientów w podziale na dane grupy.
Jedynie Figure 6 wykazuje minimalną różnicę - osoby młodsze dokonują częstszych zakupów w kategorii Intimates.
Liczba obserwacji w danych grupach
Przed przystąpieniem do budowy modeli warto również sprawdzić jak obserwacje rozkładają się między kategoriami danych zmiennych jakościowych.
| Category | n |
|---|---|
| General | 11664 |
| General Petite | 6778 |
| Initmates | 1220 |
W kategorii General jest ponad połowa obserwacji, najmniej zakupów było dokonanych w kategorii Intimates.
| Location | n |
|---|---|
| Bangalore | 4405 |
| Chennai | 1959 |
| Gurgaon | 7361 |
| Mumbai | 5937 |
Najmniej zakupów było dokonanych z lokalizacji Chennai, a najwięcej z Gurgaon.
| Channel | n |
|---|---|
| Mobile | 8271 |
| Web | 11391 |
O wiele częściej zakupy były dokonywane poprzez stronę internetową. Klienci rzadziej sięgają po aplikacje mobilne w celach zakupowych.
| Rating | n |
|---|---|
| 1 | 691 |
| 2 | 1360 |
| 3 | 2464 |
| 4 | 4289 |
| 5 | 10858 |
Znaczną większość stanowi liczba pięciu gwiazdek, które klienci zostawiają w opiniach - przeważają produkty, które zadowalają klientów.
| Recommend Flag | n |
|---|---|
| 0 | 3575 |
| 1 | 16087 |
Prawie trzy razy częściej klienci polecają dany produkt niż go nie polecają - są zadowoleni z zakupionych produktów.
Widać, że obserwacje podzielone na kategorie każdej zmiennej jakościowej nie tworzą zbalansowanych rozkładów.
Zależności między zmiennymi jakościowymi
Żeby zbadać zależności między zmiennymi jakościowymi zostanie przeprowadzony test \(\chi ^2\) o następujących hipotezach:
\(H_0\): dwie cechy są niezależne
\(H_1\): dwie cechy są zależne
| Zmienna1 | Zmienna2 | ChiSquare | pValue |
|---|---|---|---|
| Category | Location | 3.896602e+00 | 0.6906666 |
| Category | Channel | 3.097160e-01 | 0.8565368 |
| Category | Rating | 1.877074e+01 | 0.0161350 |
| Category | Recommend Flag | 9.003461e+00 | 0.0110898 |
| Location | Channel | 4.830490e+00 | 0.1846387 |
| Location | Rating | 9.320915e+00 | 0.6753031 |
| Location | Recommend Flag | 6.923299e-01 | 0.8750065 |
| Channel | Rating | 6.276955e+00 | 0.1793978 |
| Channel | Recommend Flag | 1.208978e+00 | 0.2715346 |
| Rating | Recommend Flag | 1.400219e+04 | 0.0000000 |
Table 8 przedstawia wyniki testu \(\chi ^2\). Na podstawie wyników można stwierdzić, że pary zmiennych:
CategoryiRatingCategoryiRecommend FlagRatingiRecommend Flag
są zależne - dla tych par wartość \(p < 0.05\), więc \(H_0\) zostaje odrzucona, a przyjęta \(H_1\).
Dla pozostałych połączeń zmiennych nie ma podstaw do odrzucenia \(H_0\) - można przypuszczać, że nie są zależne.
Modele - zmienna przewidywana Rating
Na wstępie z danych zostają wylosowane 3000 obserwacji i podzielone na zbiór uczący oraz testowy (gdyby możliwości sprzętowe i czasowe pozwoliły, to modele uczyłyby się na całym zbiorze danych). Zmienna objaśniana w podziale obserwacji na grupy nie jest zbalansowana, więc zostało zastosowane losowanie warstwowe względem tej zmiennej. Do budowy i poszukiwania najbardziej optymalnych parametrów w każdym modelu wykorzystywana jest 5 - krotna walidacja krzyżowa według zmiennej Rating i przeszukiwanie siatki z wykorzystaniem hipersześcianów łacińskich.
Przygotowanie zmiennej tekstowej odbywa się w funkcji recipe - tokenizacja, usunięcie zbędnych słów i filtracja tekstu.
Badany jest wpływ zmiennej Review Text na Rating.
Parametry każdego modelu wybierane są na podstawie jak najlepszych wartości pola pod wykresem krzywej ROC.
Drzewo decyzyjne
| cost_complexity | tree_depth | min_n | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 0.0000000 | 13 | 15 | roc_auc | hand_till | 0.5962653 | 5 | 0.0082392 | Preprocessor1_Model1 |
| 0.0000118 | 7 | 12 | roc_auc | hand_till | 0.5769307 | 5 | 0.0059170 | Preprocessor1_Model2 |
| 0.0006436 | 2 | 38 | roc_auc | hand_till | 0.5128334 | 5 | 0.0074239 | Preprocessor1_Model3 |
Las losowy
| mtry | trees | min_n | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 1 | 1380 | 25 | roc_auc | hand_till | 0.6673752 | 5 | 0.0068279 | Preprocessor1_Model1 |
| 8 | 1019 | 8 | roc_auc | hand_till | 0.6670670 | 5 | 0.0031381 | Preprocessor1_Model2 |
| 6 | 49 | 38 | roc_auc | hand_till | 0.6497610 | 5 | 0.0067384 | Preprocessor1_Model3 |
Boosting
| trees | min_n | tree_depth | learn_rate | loss_reduction | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|---|---|
| 765 | 9 | 15 | 0.0154253 | 0.0000001 | roc_auc | hand_till | 0.6533869 | 5 | 0.0056913 | Preprocessor1_Model1 |
| 1577 | 28 | 3 | 0.0657737 | 0.0000033 | roc_auc | hand_till | 0.6387781 | 5 | 0.0072926 | Preprocessor1_Model3 |
| 190 | 18 | 6 | 0.0012810 | 0.0623363 | roc_auc | hand_till | 0.6146494 | 5 | 0.0078729 | Preprocessor1_Model2 |
kNN
| neighbors | weight_func | dist_power | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 6 | gaussian | 0.4439849 | roc_auc | hand_till | 0.5818218 | 5 | 0.0184076 | Preprocessor1_Model2 |
| 11 | cos | 1.5112256 | roc_auc | hand_till | 0.5654947 | 5 | 0.0149985 | Preprocessor1_Model1 |
| 4 | rectangular | 0.9318431 | roc_auc | hand_till | 0.5515360 | 5 | 0.0144360 | Preprocessor1_Model3 |
Metoda wektorów nośnych
| cost | degree | scale_factor | margin | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|---|
| 0.0015851 | 1 | 0.0075874 | 0.0602313 | roc_auc | hand_till | 0.6405182 | 5 | 0.0064931 | Preprocessor1_Model2 |
| 2.4636789 | 2 | 0.0000036 | 0.1335861 | roc_auc | hand_till | 0.6399475 | 5 | 0.0064536 | Preprocessor1_Model3 |
| 0.0676736 | 3 | 0.0000000 | 0.0851141 | roc_auc | hand_till | 0.6048937 | 5 | 0.0104977 | Preprocessor1_Model1 |
Porównanie modeli
| Accuracy | AUC | |
|---|---|---|
| Drzewo decyzyjne | 0.5478723 | 0.6022062 |
| Las losowy | 0.5372340 | 0.6875062 |
| Boosting | 0.5718085 | 0.6852818 |
| k - najbliższych sąsiadów | 0.5372340 | 0.5835142 |
| SVM | 0.5372340 | 0.6673079 |
XGBoost najlepiej wypada w końcowym porównaniu.
Modele - zmienna przewidywana Recommend Flag
Ze względów na to, że zmienna Rating ma aż 5 klas, można spróbować przewidzieć zmienną dwuklasową - Recommend Flag. Może okazać się, że klasyfikacja na podstawie tekstu uda się lepiej w przypadku zmiennej objaśnianej binarnej.
Modele budowane są na takiej samej zasadzie jak powyżej. Trzeba zmienić formułę w recipe oraz zmienną według której zastosowane jest losowanie warstwowe w podziale na zbiór treningowy i testowy.
Drzewo decyzyjne
| cost_complexity | tree_depth | min_n | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 0.0000000 | 13 | 15 | roc_auc | binary | 0.7482196 | 5 | 0.0136398 | Preprocessor1_Model1 |
| 0.0000118 | 7 | 12 | roc_auc | binary | 0.6565835 | 5 | 0.0266761 | Preprocessor1_Model2 |
| 0.0006436 | 2 | 38 | roc_auc | binary | 0.5569242 | 5 | 0.0057475 | Preprocessor1_Model3 |
Las losowy
| mtry | trees | min_n | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 1 | 1380 | 25 | roc_auc | binary | 0.8681068 | 5 | 0.0127047 | Preprocessor1_Model1 |
| 8 | 1019 | 8 | roc_auc | binary | 0.8534865 | 5 | 0.0078868 | Preprocessor1_Model2 |
| 6 | 49 | 38 | roc_auc | binary | 0.8363242 | 5 | 0.0101090 | Preprocessor1_Model3 |
Boosting
| trees | min_n | tree_depth | learn_rate | loss_reduction | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|---|---|
| 765 | 9 | 15 | 0.0154253 | 0.0000001 | roc_auc | binary | 0.8117889 | 5 | 0.0107002 | Preprocessor1_Model1 |
| 1577 | 28 | 3 | 0.0657737 | 0.0000033 | roc_auc | binary | 0.7341020 | 5 | 0.0034118 | Preprocessor1_Model3 |
| 190 | 18 | 6 | 0.0012810 | 0.0623363 | roc_auc | binary | 0.7137996 | 5 | 0.0088562 | Preprocessor1_Model2 |
kNN
| neighbors | weight_func | dist_power | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|
| 11 | cos | 1.5112256 | roc_auc | binary | 0.7087262 | 5 | 0.0159316 | Preprocessor1_Model1 |
| 6 | gaussian | 0.4439849 | roc_auc | binary | 0.6813468 | 5 | 0.0220856 | Preprocessor1_Model2 |
| 4 | rectangular | 0.9318431 | roc_auc | binary | 0.6378725 | 5 | 0.0247270 | Preprocessor1_Model3 |
Metoda wektorów nośnych
| cost | degree | scale_factor | margin | .metric | .estimator | mean | n | std_err | .config |
|---|---|---|---|---|---|---|---|---|---|
| 0.0676736 | 3 | 0.0000000 | 0.0851141 | roc_auc | binary | 0.8408480 | 5 | 0.0157856 | Preprocessor1_Model1 |
| 2.4636789 | 2 | 0.0000036 | 0.1335861 | roc_auc | binary | 0.8134617 | 5 | 0.0167795 | Preprocessor1_Model3 |
| 0.0015851 | 1 | 0.0075874 | 0.0602313 | roc_auc | binary | 0.8133200 | 5 | 0.0168427 | Preprocessor1_Model2 |
Porównanie modeli
| Accuracy | AUC | |
|---|---|---|
| Drzewo decyzyjne | 0.8120000 | 0.7184531 |
| Las losowy | 0.8146667 | 0.8774153 |
| Boosting | 0.8346667 | 0.8252540 |
| k - najbliższych sąsiadów | 0.8053333 | 0.6765592 |
| SVM | 0.8146667 | 0.8397956 |
XGBoost i las losowy dają nalepsze wyniki w klasyfikacji.
Wnioski
Na podstawie zbudowanych modeli można stwierdzić, że przewidywanie ograniczonej zmiennej klasyfikacyjnej (binarnej) jest dużo bardziej efektywne i dokładne niż przewidywanie przynależności do pięciu klas. Modelem, który najlepiej radzi sobie z przewidywaniem na podstawie tekstu z tego zbioru danych jest XGBoost. Widać, że istnieje zależność między opinią, którą wystawia klient, a ostateczną oceną i ewentualną rekomendacją.
Źródła
https://www.kaggle.com/datasets/rishikumarrajvansh/womens-clothing-reviews-data